package Pieces;
import java.awt.geom.*;
import java.util.Random;
import java.awt.Point;


public class Board {

    public static final int BOARD_WIDTH = 10;
    public static final int BOARD_HEIGHT = 20;
    public static final int PIECE_SIZE = 4;
    private static final int[] probs = {L.PROBABILITY, Pipe.PROBABILITY,
                                        ReverseL.PROBABILITY, ReverseSquigly.PROBABILITY,
                                        Square.PROBABILITY, Squigly.PROBABILITY,
                                        Tee.PROBABILITY};
    //the probabilities of each piece.  If you change the order, change the order in getRandomPiece()

    private Random rand;
     public Piece activePiece;
     public Piece nextPiece;
     public BlockType[][] blob;
     public BlockType[][] board;
     
     public Board(){
    	 board = new BlockType[BOARD_HEIGHT][BOARD_WIDTH];
    	 blob = new BlockType[BOARD_HEIGHT][BOARD_WIDTH];
    	 initBoard();
    	 initBlob();
    	 
    	 activePiece = getRandomPiece(); //create new Piece 4x4
    	 nextPiece = getRandomPiece(); //create new Piece 4x4
         rand = new Random();
     }
     

     public void initBoard(){
    	 for(int i=0;i<BOARD_HEIGHT;i++){
    		 for(int j=0;j<BOARD_WIDTH;j++){
    			 board[i][j] = BlockType.NONE;
    		 }
    	  }
     }
     
     public void initBlob(){
    	 for(int i=0;i<BOARD_HEIGHT;i++){
    		 for(int j=0;j<BOARD_WIDTH;j++){
    			 blob[i][j] = BlockType.NONE;
    		 }
    	  }
     }
     
     public Piece getRandomPiece()
     {
//         int num = rand.nextInt(100);
//
//         int piece = 0;
//         while(num > 0) //get which section of probabilities the random number fell
//         {
//             num -= probs[piece];
//             piece++;
//         }
//
//         switch(piece - 1)
//         {
//             case 0: return new L();
//             case 1: return new Pipe();
//             case 2: return new ReverseL();
//             case 3: return new ReverseSquigly();
//             case 4: return new Square();
//             case 5: return new Squigly();
//             case 6: return new Tee();
//         }

    	 return new Pipe();
     }
     
     public void rotateActivePiece()
     {
    	 activePiece.changeState();

         if(testRotateCollision())
         {
             activePiece.restoreState();
         }
         else
         {
            translatePiecesToBoard();
         }
     }

     //use negative for left, positive for right
     public void movePiece(int howMuch)
     {
         if(!testLeftRightCollision())
         {
             int x = activePiece.getPosition().x + howMuch;
             int y = activePiece.getPosition().y;
             activePiece.setPosition(x, y);
             translatePiecesToBoard();
         }
     }

     //drops the piece down as far as it will go
     public void instantDrop()
     {
         while(!testDropCollision()) //while no collision
         {
             int x = activePiece.getPosition().x;
             int y = activePiece.getPosition().y;
             activePiece.setPosition(x, y+1);
         }

         translatePiecesToBoard();
     }
     
     /*
      * moves the active piece down by 1
      */
     public void dropActivePiece(){

    	 int col = activePiece.getPosition().x;
    	 int row = activePiece.getPosition().y;
    	 
    	 if(row != (BOARD_HEIGHT - PIECE_SIZE))
    		 activePiece.setPosition(col, row+1);
    	 else
    		 swapActiveAndNextPiece();
    	 
    	 translatePiecesToBoard();
     }
     
     /*
      * makes the next piece become the active piece
      */
     public void swapActiveAndNextPiece(){
    	 activePieceToBlob();
    	 activePiece = nextPiece;
    	 nextPiece = getRandomPiece();
     }
     
     /*
      * translates the active piece to the blob
      */
     public void activePieceToBlob(){
    	 double cols = activePiece.getPosition().getX();
    	 double rows = activePiece.getPosition().getY();
    	 BlockType[][] piece = activePiece.getCurrentBlockArray();
    	 for(int i=0;i < PIECE_SIZE;i++){
		   for(int j=0;j < PIECE_SIZE;j++){
			   blob[(int)(rows+j)][(int)(cols+i)] = piece[i][j];
		   }
    	 }
     }
     
     public void translatePiecesToBoard(){
    	 
    	 //First, copy the "blob's" blocks to our board
    	 BlockType[][] piece = activePiece.getCurrentBlockArray();
    	 
    	  for(int i=0;i<BOARD_HEIGHT;i++){
    		 for(int j=0;j<BOARD_WIDTH;j++){
    			 board[i][j] = blob[i][j];
    		 }
    	  }
    	 
   
    	 //Second, copy the "activePiece" blocks to the 
    	 //appropriate place on the board using the coordinates
    	 //of the activePiece
    	 double cols = activePiece.getPosition().getX();
    	 double rows = activePiece.getPosition().getY();
    	 for(int i=0;i < PIECE_SIZE;i++){
		   for(int j=0;j < PIECE_SIZE;j++){
			   board[(int)(rows+j)][(int)(cols+i)] = piece[i][j];
		   }
    	 }
    	 
     }
     
     public BlockType[][] getBoard(){
    	 return board;
     }
     
   
     private boolean testDropCollision()
     {
         BlockType[][] currentState = activePiece.getCurrentBlockArray();

         int starty = activePiece.getPosition().y + 1; //check one space below

         if(testBottomCollision())
             return true;

         int stopy = starty + PIECE_SIZE;
         if(stopy > (BOARD_HEIGHT - 1))
         {
             stopy = BOARD_HEIGHT -1;
         }

         int startx = activePiece.getPosition().x;

         for(int y = 0; y < (stopy - starty); y++)
         {
             for(int x = 0; x < PIECE_SIZE; x++)
             {
                 if(currentState[x][y] != BlockType.NONE)
                 {
                     if(blob[startx + x][starty + y] != BlockType.NONE)
                     {
                         return true;
                     }
                 }
             }
         }

         return false;
     }

     //returns true if collision, false if not
     private boolean testBottomCollision()
     {
         BlockType[][] currentState = activePiece.getCurrentBlockArray();
         int starty = activePiece.getPosition().y;

         int bottom;
         for(bottom = 3; bottom >= 0; bottom--)
         {
             for(int x = 0; x < 4; x++)
             {
                 if(currentState[x][bottom] != BlockType.NONE)
                 {
                     break;
                 }
             }
         }

         return (bottom + starty > BOARD_HEIGHT) ? true : false;
     }

     //returns true if collision, false if not
     private boolean testLeftRightCollision()
     {
         BlockType[][] currentState = activePiece.getCurrentBlockArray();
         int left = PIECE_SIZE;
         int right = 0;

         for(int y = 0; y < PIECE_SIZE; y++)
         {
             for(int x = 0; x < PIECE_SIZE; x++)
             {
                 if(currentState[x][y] != BlockType.NONE)
                 {
                     if(x < left)
                     {
                         left = x;
                     }
                     if(x > right)
                     {
                         right = x;
                     }
                 }
             }
         }

         return (left < 0 || right > BOARD_WIDTH - 1) ? true : false;
     }

     //returns true if collision, false if not
     public boolean testRotateCollision()
     {
         return (testDropCollision() || testLeftRightCollision()) ? true : false;
     }
}
